package sokoban;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundRepeat;
import javafx.scene.layout.BackgroundSize;
import javafx.scene.layout.Pane;

public class MapPane extends Pane {
	 // The cell size
	public final static int CELL_SIZE = 64;
	// All images for element displaying
	private Image[] icons;
	// Logical storage space for all elements
	private ImageView[][] map;
	// Controlled object
	private Man man;
	private Box box;
	private Wall wall;
	private Target target;
	// Mission points
	private List<ImageView> targets;
	// Number of cells
	private int xlength;
	private int ylength;
	// Constructor.
	 public MapPane(Image[] iconList, File mapFile)
	 {
		 icons = iconList;
		 // Load map
		 this.loadMap(mapFile);

		 // Set background
		 Background bg = new Background(
				 new BackgroundImage(
						 iconList[Element.BACKGROUND],
						 BackgroundRepeat.REPEAT,
						 BackgroundRepeat.REPEAT,
						 BackgroundPosition.DEFAULT,
						 new BackgroundSize(
								 BackgroundSize.AUTO,
								 BackgroundSize.AUTO,
								 true, true, false, false)
						 )
				 );
		 setBackground(bg);
	 }

	 // Clear old data and load new map data
	 public void loadMap(File mapFile) {
		try(Scanner input = new Scanner(mapFile))
		{
			 // Get length information from the first line in the map file
			String[] items = input.nextLine().split(",");
			int xlen = Integer.parseInt(items[0]);
			int ylen = Integer.parseInt(items[1]);
			xlength = xlen;
			ylength = ylen;
			// Initialize and clear the map pane
			this.map = new ImageView[xlen][ylen];
			targets = new ArrayList<ImageView>();
			this.getChildren().clear();
			// Read file and add elements to the map pane
			while(input.hasNextLine())
			{
				 // Get information of a element from string parsing
				items = input.nextLine().split(",");
				int x = Integer.parseInt(items[0]);
				int y = Integer.parseInt(items[1]);
				int type = Integer.parseInt(items[2]);
				// Create an element
				Element e = null;
				switch(type)
				{
				
					case Element.MAN:e = this.man = new Man(icons[Element.MAN]);
					break;
					case Element.BOX:e = this.box = new Box(icons[Element.BOX]);
					break;
					case Element.WALL:e = this.wall = new Wall(icons[Element.WALL]);
					break;
					case Element.TARGET:e = this.target = new Target(icons[Element.TARGET]);
					break;
					default:break;
				}
				// Set the position and display the element
				e.setX(x * CELL_SIZE);
				e.setY(y * CELL_SIZE);
				getChildren().add(e);
				// Add element to the logical map
				if(e instanceof Target)
				{
					targets.add(e);
				}
				else 
				{
					this.map[x][y] = e;
				}
			}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
	}
	// Judge the state of the game
	public boolean judge()
	{
		boolean win = true;
		for(ImageView i:targets)
		{
			int x = (int) (i.getX() / CELL_SIZE);
			int y = (int) (i.getY() / CELL_SIZE);
			if(!(map[x][y] instanceof Box))
			{
				win = false;
				break;
			}
		}
		return win;
	}
	// How to move the man and boxes in the upward direction
	public void moveManUp()
	{
		int manX = (int) (man.getX() / CELL_SIZE);
		int manY = (int) (man.getY() / CELL_SIZE);
		if(manY >= 0 && manY<ylength)
		{
			if(map[manX][manY - 1] == null)
			{
				man.up();
				map[manX][manY] = null;
				map[manX][manY - 1] = man;
			}
			else if(map[manX][manY - 1] instanceof Box)
			{
				System.out.println("hahah");
				if(manY - 1 > 0 && map[manX][manY - 2] == null)
				{
					Box b = (Box) map[manX][manY - 1];
					b.up();
					map[manX][manY - 2] = b;
					man.up();
					map[manX][manY] = null;
					map[manX][manY - 1] = man;
				}
			}
		}
	}
	// How to move the man and boxes in the downward direction
	public void moveManDown() 
	{
		int manX = (int) (man.getX() / CELL_SIZE);
		int manY = (int) (man.getY() / CELL_SIZE);
		if(manY >= 0 && manY<ylength)
		{
			if(map[manX][manY + 1] == null)
			{
				man.down();
				map[manX][manY] = null;
				map[manX][manY + 1] = man;
			}
			else if(map[manX][manY + 1] instanceof Box)
			{
				System.out.println("hahah");
				if(manY + 1<ylength && map[manX][manY + 2] == null)
				{
					Box b = (Box) map[manX][manY + 1];
					b.down();
					map[manX][manY + 2] = b;
					man.down();
					map[manX][manY] = null;
					map[manX][manY + 1] = man;
				}
			}
		}
	
	}
	// How to move the man and boxes in the leftward direction
	public void moveManLeft()
	{
		int manX = (int) (man.getX() / CELL_SIZE);
		int manY = (int) (man.getY() / CELL_SIZE);
		if(manX >= 0 && manX<xlength)
		{
			if(map[manX - 1][manY] == null)
			{
				man.left();
				map[manX][manY] = null;
				map[manX - 1][manY] = man;
			}
			else if(map[manX - 1][manY] instanceof Box)
			{
				System.out.println("hahah");
				if(manX - 1 > 0 && map[manX - 2][manY] == null)
				{
					Box b = (Box) map[manX-1][manY];
					b.left();
					map[manX - 2][manY] = b;
					man.left();
					map[manX][manY] = null;
					map[manX - 1][manY] = man;
				}
			}
		}
		
	
	}
	// How to move the man and boxes in the rightward direction
	public void moveManRight()
	{
		int manX = (int) (man.getX() / CELL_SIZE);
		int manY = (int) (man.getY() / CELL_SIZE);
		if(manX >= 0 && manX<xlength)
		{
			if(map[manX + 1][manY] == null)
			{
				man.right();
				map[manX][manY] = null;
				map[manX+1][manY] = man;
			}
			else if(map[manX + 1][manY] instanceof Box)
			{
				System.out.println("hahah");
				if(manX + 1 < xlength && map[manX + 2][manY] == null)
				{
					Box b = (Box) map[manX + 1][manY];
					b.right();
					map[manX + 2][manY] = b;
					man.right();
					map[manX][manY] = null;
					map[manX + 1][manY] = man;
				}
			}
		}
	
	}
}

